#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>

using std::cout;
using std::endl;
using std::ostringstream;

void server()
{
    int sockFd = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in addr{}, clt{};
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_port = htons(12345);
    addr.sin_family = AF_INET;

    int opt = 1;
    setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    setsockopt(sockFd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
    bind(sockFd, (sockaddr *)&addr, sizeof(addr));

    listen(sockFd, 128);

    socklen_t len = sizeof(clt);
    std::ostringstream oss;
    while (1)
    {
        memset(&clt, 0, sizeof(len));
        memset(&len, 0, sizeof(len));
        int cltFd = accept(sockFd, (sockaddr *)&clt, &len);
        char buf[1024]{};
        while (1)
        {
            memset(buf, 0, strlen(buf));
            int ret = read(cltFd, buf, sizeof(buf));
            if (ret == 0)
            {
                oss << inet_ntoa(clt.sin_addr) << ": "
                    << ntohs(clt.sin_port);

                cout << oss.str();
                oss.clear();
                break;
            }
            cout << "msg from client: " << buf;
        }
        close(cltFd);
    }

    close(sockFd);
}

int main(int args, char *argv[])
{
    server();
    return 0;
}